using System;
using System.Collections.Generic;
using StrategyGame.Model;

namespace StrategyGame.Scripts
{
    public static class PeopleManager
    {
        public static List<Person> People { get; set; }
        public static List<Relationship> Relationships { get; set; }

        public static event EventHandler OnMarriage;
        public static event EventHandler OnBirth;
        public static event EventHandler OnDeath;

        private static void InvokeOnBirth(EventArgs e)
        {
            EventHandler handler = OnBirth;
            if (handler != null) handler(null, e);
        }

        private static void InvokeOnDeath(EventArgs e)
        {
            EventHandler handler = OnDeath;
            if (handler != null) handler(null, e);
        }

        private static void InvokeOnMarriage(EventArgs e)
        {
            EventHandler handler = OnMarriage;
            if (handler != null) handler(null, e);
        }

        private static List<Person> _men;
        private static List<Person> _women;
        private static List<Person> _deadPeople;

        private static List<Person> _children;

        public static void Initialize(int seed)
        {
            People = new List<Person>();
            Relationships = new List<Relationship>();
            _men = new List<Person>();
            _women = new List<Person>();
            _deadPeople = new List<Person>();
            _children = new List<Person>();

            Random random = new Random(seed);

            for (int c = 0; c < 52; c++)
            {
                Person person = new Person {FamilyName = Names.Family[c]};
                if (random.Next(100) < 49)
                {
                    person.IsMale = true;
                }
                _children.Add(person);
                People.Add(person);
            }
        }
        public static void AgeWorldByYear(int seed)
        {
            Random random = new Random(seed);

            for (int c = People.Count-1; c >= 0; c--)
            {
                Person person = People[c];
                if (random.Next(0, 1000) < person.DeathChance)
                {
                    Death(c, person);
                }
                else
                {
                    person.Age++;
                    person.DeathChance += 1;
                    if (person.Age == 16)
                    {
                        person.BirthChance = 30;
                        person.RelationshipChance = 70;
                        if (person.IsMale) _men.Add(person); else _women.Add(person);
                        _children.Remove(person);
                    } 
                    else if (person.Age > 16)
                    {
                        person.RelationshipChance++;
                    }

                    if (!person.IsMale)
                    {
                        Person woman = person;
                        if (woman.Partner == null && random.Next(0, 100) < person.RelationshipChance)
                        {
                            Person man = GetHusband(random);

                            if (man.Partner == null)
                            {
                                Marry(woman, man);
                            }
                        }
                        if (woman.Partner != null && !woman.Partner.IsDead && random.Next(0, 100) < person.BirthChance)
                        {
                            Person baby = woman.GiveBirth(woman.Partner, random);
                            if (baby != null)
                            {
                                People.Add(baby);
                                _children.Add(baby);
                                InvokeOnBirth(new EventArgs());
                                woman.BirthChance -= 20;
                            } else
                            {
                                woman.BirthChance = 0;
                            }
                        }
                    }
                }
            }
        }

        private static void Death(int c, Person person)
        {
            person.IsDead = true;
            People.RemoveAt(c);
            _deadPeople.Add(person);
            if (person.Age < 16)
            {
                _children.Remove(person);
            }
            else
            {
                if (person.IsMale)
                {
                    _men.Remove(person);
                }
                else
                {
                    _women.Remove(person);
                }
            }
            InvokeOnDeath(new EventArgs());
        }

        private static void Marry(Person woman, Person man)
        {
            woman.Partner = man;
            man.Partner = woman;
            Relationship relationship = new Relationship()
                                            {
                                                People = new List<Person> { man, woman},
                                                Type = RelationshipType.Married
                                            };
            man.Relationships.Add(relationship);
            woman.Relationships.Add(relationship);
            Relationships.Add(relationship);
            man.RelationshipChance = 0;
            woman.RelationshipChance = 0;
            woman.BirthChance += 30;
            InvokeOnMarriage(new EventArgs());
        }

        private static Person GetHusband(Random random)
        {
            Person man;
            int loopCounter = 0;
            do
            {
                man = _men[random.Next(0, _men.Count)];
                loopCounter++;
            } while (man.Partner != null && loopCounter < 5);
            return man;
        }
    }
}